package com.liuqing.www.java基础知识.NIO;

import java.io.FileNotFoundException;
import java.nio.channels.FileChannel;

/**
 * nio==new io
 * <li>与io的区别，NIO 以块的方式处理数据。 而io以流的方式处理数据（效率低下）
 * <li>通道与流的不同之处在于通道是双向的。
 * <li>所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中，相反，您是将数据写入包含一个或者多个字节的缓冲区。同样，您不会直接从通道中读取字节，而是将数据从通道读入缓冲区，再从缓冲区获取这个字节。 
 * <li>最常用的缓冲区类型是 ByteBuffer。一个 ByteBuffer 可以在其底层字节数组上进行 get/set 操作(即字节的获取和设置)。 
 * <li>Buffer 是一个对象， 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象，体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中，您将数据直接写入或者将数据直接读到 Stream 对象中。
 * <li>异步IO的支持可以算是NIO API中最重要的功能，异步IO允许应用程序同时监控多个channel以提高性能，这一功能是通过Selector，SelectableChannel和SelectionKey这3个类来实现的。
SelectableChannel代表了可以支持异步IO操作的channel，可以将其注册在Selector上，这种注册的关系由SelectionKey这个类来表现（见UML图）。Selector这个类通过select()函数，给应用程序提供了一个可以同时监控多个IO channel的方法：
内存映射文件I/O是一种读和写文件数据的方法，它可以比常规的基于流或者基于通道的I/O快得多。
MappedByteBuffer 
 * buffer非线程安全
 * @author 韩世超
 *
 */
public class NIOTest {

	/**好处在于可以异步io直接改缓存，且不用再
	 * @param args
	 */
	public static void main(String[] args) {
		 java.io.RandomAccessFile raf;
		try {
			raf = new java.io.RandomAccessFile("e://xx","rw");
	        long totalLen=raf.length();   
	        System.out.println("文件总长字节是: "+totalLen);   
	        //打开一个文件通道   
	        java.nio.channels.FileChannel channel=raf.getChannel();   
	        //映射文件中的某一部分数据以读写模式到内存中   
	        java.nio.MappedByteBuffer buffer=  channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);   
	        //示例修改字节   
	        for(int i=0;i<10;i++){   
	        byte src=   buffer.get(i);   
	        buffer.put(i,(byte)(src-31));//修改Buffer中映射的字节的值   
	        System.out.println("被改为大写的原始字节是:"+src);   
	       }   
	        buffer.force();//强制输出,在buffer中的改动生效到文件   
	        buffer.clear();   
	        channel.close();   
	        raf.close();   
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
/**
FileInputStream fis = new FileInputStream("C:/Java/jdk1.6.0_18/LICENSE");
03. 
04.    // 得到文件通道
05.    FileChannel fc = fis.getChannel();
06. 
07.    // 指定大小为 1024 的缓冲区
08.    ByteBuffer bf = ByteBuffer.allocate(1024);
09. 
10.    // 读取通道中的下一块数据到缓冲区中
11.    // 缓冲区的 position 即为当前缓冲区中最后有效位置
12.    while (fc.read(bf) != -1) {
13. 
14.        //把缓冲中当前位置回复为零，前把缓冲区的 limit 设置为之前 position 值
15.        bf.flip();
16. 
17.        // 输出缓冲区中的内容
18.        while (bf.hasRemaining()) {
19.            System.out.print((char) bf.get());
20.        }
21. 
22.        // 清理缓冲区，准备再次读取数据
23.        bf.clear();
24.    }



 * 有两种类型的文件IO同步：同步文件IO和异步文件IO。异步文件IO也就是重叠IO。在同步文件IO中，线程启动一个IO操作然后就立即进入等待状态，直到IO操作完成后才醒来继续执行。而异步文件IO方式中，线程发送一个IO请求到内核，然后继续处理其他的事情，内核完成IO请求后，将会通知线程IO操作完成了。

如果IO请求需要大量时间执行的话，异步文件IO方式可以显著提高效率，因为在线程等待的这段时间内，CPU将会调度其他线程进行执行，如果没有其他线程需要执行的话，这段时间将会浪费掉（可能会调度操作系统的零页线程）。如果IO请求操作很快，用异步IO方式反而还低效，还不如用同步IO方式。
同步IO在同一时刻只允许一个IO操作，也就是说对于同一个文件句柄的IO操作是序列化的，即使使用两个线程也不能同时对同一个文件句柄同时发出读写操作。重叠IO允许一个或多个线程同时发出IO请求。
异步IO在请求完成时，通过将文件句柄设为有信号状态来通知应用程序，或者应用程序通过GetOverlappedResult察看IO请求是否完成，也可以通过一个事件对象来通知应用程序。

简单的说“同步在编程里，一般是指某个IO操作执行完后，才可以执行后面的操作。异步则是，将某个操作给系统，主线程去忙别的事情，等内核完成操作后通知主线程异步操作已经完成。”
*/
